/***************************************************************************

  Defines classes and functions required for operations on files 
  and terminals.

 ***************************************************************************/
#include <map>
#include <netcdfcpp.h>
#include <vector>
#include "datatypes.h"
#include <mpParser.h>

#ifndef QGCM_IO_HEADER
#define QGCM_IO_HEADER
using namespace std;

/* ---------------------------------------------------- */
/* Define qstream class */
class qstream {
	FILE * stream;
	string path;
	string ifmt;
	enum stype { pipe, socket, terminal, regular, internal, closed, unknown };
	stype ftype;
	public:
	qstream();
	~qstream();
	qstream(const qstream &);
	qstream(FILE *);
	qstream & operator=(const qstream &);
	private:
	void set_ftype();
	public:
	int printf(const char * fmt, ...) const;
	int vprintf(const char * fmt, va_list arg) const;
	int scanf(const char * fmt, ...) const;
	void flush() const;
	bool close();
	bool open(const char *, const char *);
	bool open(FILE *);
	bool reopen() ;
	bool putc(char c) const;
	bool is_interactive_input() const;
	bool is_fifo() const;
	bool is_terminal_device() const;
	bool is_pipe() const;
	bool is_socket() const;
	bool is_closed() const;
	FILE * get_handle();

	const string & getpath() const;


	const qstream & operator<<(const int &) const;
	const qstream & operator<<(const float &) const ;
	const qstream & operator<<(const double &) const ;
	const qstream & operator<<(const string &) const ;
	const qstream & operator<<(const bool &) const ;
	const qstream & operator<<(const mup::IValue &) const;

	static const qstream & getroutqstream();
};
/* global interface : */
/* ---------------------------------------------------- */
void terminal_readline(string &, const char *, const qstream & in, const qstream & out);
int read_fifo(const char *, vector<string> &);
bool is_file_terminal_device(const char *);
bool is_file_pipe(const char *);
bool is_file_socket(const char *);
void redirectoutputstreamsfornohup();
/* ---------------------------------------------------- */
/* Define nc classes */
template <class T>
class nc_attribute {
	string name;
	T value;
	public:
	nc_attribute(const string & name, const T & value);
};
/* ---------------------------------------------------- */
class ncstream { // interface class for netcdf output
	enum filemode { read, overwrite, newwrite, append };
	private:
	NcFile * ncbuf;
	ncstream(const ncstream & );
	void operator=(const ncstream &);
	public:
	ncstream();
	bool open(const char * fname, filemode fmode);
	bool write_variable_attributes( const char * varname, const vector< pair< string, string > > & attribs ); 
	bool write_variable_attributes( const char * varname, const vector< pair< string, int > > & attribs ); 
	bool write_variable_attributes( const char * varname, const vector< pair< string, float > > & attribs );
	bool add_variable_missing_value_attribute(const char * varname, const REAL & );
	bool add_dimension( const char * name, int size ); 
	bool add_dimension( const char * name );
	bool write_array( const vector<REAL> &, const char * dimname ); 
	bool write_array( const vector<int> &, const char * dimname ); 
	bool close();
};
/* ---------------------------------------------------- */
bool check_stream_output_status(const char *, const char * & errormsg);  // function returns true if the file 
// 1) does not exist (can be written to safetly
// 2) is a terminal device
// otherwise returns false;
/* ---------------------------------------------------- */
class nchandler {
	private:
		map< int, NcFile * > ncfiles;
		int c_hid;

		nchandler(const nchandler &);
		void operator=(const nchandler &);
		int generate_hid();
	public:
		nchandler();
		~nchandler();
		NcFile * getncfile(const int & handle);
		bool deletencfile(const int & handle);
		int createncfile(const char *, NcFile::FileMode);
};



#endif
